package bg.btanev.eightyfour.client.view;

import java.util.List;

import bg.btanev.eightyfour.client.presenter.ProfilesPresenter.ProfilesDisplay;
import bg.btanev.eightyfour.client.utils.SelectionUtils;
import bg.btanev.eightyfour.shared.dto.profile.ProfileDto;
import bg.btanev.eightyfour.shared.dto.profile.ProfileEventDto;
import bg.btanev.eightyfour.shared.dto.profile.feed.FeedProfileDto;
import bg.btanev.eightyfour.shared.state.ProfileType;

import com.google.gwt.event.dom.client.HasClickHandlers;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.CaptionPanel;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.Grid;
import com.google.gwt.user.client.ui.HasHorizontalAlignment;
import com.google.gwt.user.client.ui.HasText;
import com.google.gwt.user.client.ui.HorizontalPanel;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.ListBox;
import com.google.gwt.user.client.ui.TextBox;
import com.google.gwt.user.client.ui.VerticalPanel;
import com.google.gwt.user.client.ui.Widget;

import eu.maydu.gwt.validation.client.DefaultValidationProcessor;
import eu.maydu.gwt.validation.client.actions.StyleAction;
import eu.maydu.gwt.validation.client.validators.ListBoxValidator;
import eu.maydu.gwt.validation.client.validators.standard.NotEmptyValidator;

/**
 *
 * @author B.Tanev
 *
 */
public class ProfilesView extends Composite implements ProfilesDisplay {
	private final ListBox typeData;
	private final TextBox nameData;
	private final ListBox profilesListbox;
	private final TextBox urlData;
	private final Button addNewButton;
	private final Button saveButton;
	private List<? extends ProfileDto<? extends ProfileEventDto>> profiles;
	private ProfileDto<? extends ProfileEventDto> profile;
	private Button deleteButton;
	private final DefaultValidationProcessor validator;

	public ProfilesView() {
		final VerticalPanel verticalPanel = new VerticalPanel();
		initWidget(verticalPanel);
		verticalPanel.setSpacing(5);
		verticalPanel.setSize("650px", "340px");

		final HorizontalPanel horizontalPanel = new HorizontalPanel();
		horizontalPanel.setSpacing(5);
		horizontalPanel.setSize("100%", "290px");
		verticalPanel.add(horizontalPanel);

		profilesListbox = new ListBox();
		profilesListbox.setSize("225px", "100%");
		horizontalPanel.add(profilesListbox);
		profilesListbox.setVisibleItemCount(15);

		final CaptionPanel profileDetailsPanel = new CaptionPanel("Profile Details");
		profileDetailsPanel.setHeight("100%");
		horizontalPanel.add(profileDetailsPanel);

		final Grid profileDetailsContainer = new Grid(3, 2);
		profileDetailsPanel.setContentWidget(profileDetailsContainer);
		profileDetailsContainer.setSize("100%", "");

		final Label nameCaption = new Label("Name");
		profileDetailsContainer.setWidget(0, 0, nameCaption);
		nameCaption.setWidth("100px");

		nameData = new TextBox();
		profileDetailsContainer.setWidget(0, 1, nameData);
		nameData.setWidth("300px");

		final Label typeCaption = new Label("Type");
		profileDetailsContainer.setWidget(1, 0, typeCaption);
		typeCaption.setWidth("100px");

		typeData = new ListBox();
		profileDetailsContainer.setWidget(1, 1, typeData);
		typeData.setWidth("300px");

		final Label urlCaption = new Label("URL");
		profileDetailsContainer.setWidget(2, 0, urlCaption);
		urlCaption.setWidth("100px");

		urlData = new TextBox();
		profileDetailsContainer.setWidget(2, 1, urlData);
		urlData.setWidth("300px");

		final HorizontalPanel actionButtonsContainer = new HorizontalPanel();
		actionButtonsContainer.setHorizontalAlignment(HasHorizontalAlignment.ALIGN_CENTER);
		actionButtonsContainer.setSpacing(5);
		verticalPanel.add(actionButtonsContainer);
		verticalPanel.setCellHorizontalAlignment(actionButtonsContainer, HasHorizontalAlignment.ALIGN_RIGHT);
		actionButtonsContainer.setWidth("100%");

		addNewButton = new Button("Add New");
		actionButtonsContainer.add(addNewButton);
		addNewButton.setWidth("110px");

		saveButton = new Button("Save");
		actionButtonsContainer.add(saveButton);
		saveButton.setWidth("110px");

		deleteButton = new Button("");
		deleteButton.setText("Delete");
		actionButtonsContainer.add(deleteButton);
		deleteButton.setWidth("110px");

		ProfileType[] values = ProfileType.values();
		for (ProfileType profileType : values) {
			this.typeData.addItem(profileType.name(), profileType.name());
		}

		validator = new DefaultValidationProcessor();

		validator.addValidators("profileValidation",
				new NotEmptyValidator(nameData)
					.addActionForFailure(new StyleAction("validationFailedBorder")),
				new ListBoxValidator(typeData)
					.addActionForFailure(new StyleAction("validationFailedBorder")),
				new NotEmptyValidator(urlData)
					.addActionForFailure(new StyleAction("validationFailedBorder"))
				);
	}

	public void setProfiles(List<? extends ProfileDto<? extends ProfileEventDto>> profiles) {
		clearView();
		this.profiles = profiles;
		if (this.profiles != null) {
			for (ProfileDto<? extends ProfileEventDto> profileDto : profiles) {
				this.profilesListbox.addItem(profileDto.getName(), String.valueOf(profileDto.getId()));
			}
		}
	}

	public boolean isValid() {
		return validator.validate("profileValidation");
	}

	public void clearView() {
		this.profilesListbox.setSelectedIndex(-1);
		this.profilesListbox.clear();
		setProfile(null);
		this.profiles = null;
	}

	public <P extends ProfileDto<? extends ProfileEventDto>> void setProfile(P profile) {
		this.profile = profile;
		if (this.profile != null) {
			updateProfileDetails();
		} else {
			clearProfileDetails();
		}
	}

	@SuppressWarnings("unchecked")
	public <P extends ProfileDto<? extends ProfileEventDto>> P getProfile() {
		return (P) this.profile;
	}

	private void updateProfileDetails() {
		if (this.profile != null) {
			this.nameData.setText(this.profile.getName());
			if (this.profile.getType() != null) {
				SelectionUtils.selectValueFromList(this.typeData, this.profile.getType().name());
			} else {
				this.typeData.setSelectedIndex(-1);
			}

			if (this.profile.getId() != null) {
				this.typeData.setEnabled(false);
			} else {
				this.typeData.setEnabled(true);
			}

			if (this.profile instanceof FeedProfileDto) {
				this.urlData.setText(((FeedProfileDto) profile).getFeedUrl());
			}
		}
	}

	private void clearProfileDetails() {
		nameData.setText("");
		typeData.setSelectedIndex(-1);
		urlData.setText("");
	}

	public HasClickHandlers getProfilesListbox() {
		return profilesListbox;
	}

	public HasClickHandlers getAddNewButton() {
		return addNewButton;
	}

	public HasClickHandlers getSaveButton() {
		return saveButton;
	}

	public HasClickHandlers getDeleteButton() {
		return deleteButton;
	}

	public HasText getNameData() {
		return nameData;
	}

	public ListBox getTypeData() {
		return typeData;
	}

	public HasText getUrlData() {
		return urlData;
	}

	@Override
	public Widget asWidget() {
		return this;
	}

	public ProfileType getSelectedType() {
		ProfileType type = null;
		String value = SelectionUtils.getSelectedValue(this.typeData);
		if (value != null) {
			type = ProfileType.valueOf(value);
		}
		return type;
	}

	public ProfileDto<? extends ProfileEventDto> getSelectedProfile() {
		ProfileDto<? extends ProfileEventDto> profile = null;

		int pos = this.profilesListbox.getSelectedIndex();
		if (pos >= 0) {
			profile = this.profiles.get(pos);
		}

		return profile;
	}
}
